package com.mistywood;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 * A simple Swing-based client for the chat server. Graphically it is a frame with a text field for entering messages and a textarea to see the whole dialog. The client follows the Chat Protocol which is as follows. When the server sends "SUBMITNAME" the client replies with the desired screen name.
 * The server will keep sending "SUBMITNAME" requests as long as the client submits screen names that are already in use. When the server sends a line beginning with "NAMEACCEPTED" the client is now allowed to start sending the server arbitrary strings to be broadcast to all chatters connected to
 * the server. When the server sends a line beginning with "MESSAGE " then all characters following this string should be displayed in its message area.
 */
public class Client
{
	
	BufferedReader in;
	PrintWriter out;
	JFrame frame = new JFrame("Chatter");
	JTextField textField = new JTextField(40);
	JTextArea messageArea = new JTextArea(8, 40);
	
	/**
	 * Constructs the client by laying out the GUI and registering a listener with the textfield so that pressing Return in the listener sends the textfield contents to the server. Note however that the textfield is initially NOT editable, and only becomes editable AFTER the client receives the
	 * NAMEACCEPTED message from the server.
	 */
	public Client()
	{
		
		// Layout GUI
		textField.setEditable(false);
		messageArea.setEditable(false);
		frame.getContentPane().add(textField, "North");
		frame.getContentPane().add(new JScrollPane(messageArea), "Center");
		frame.pack();
		
		// Add Listeners
		textField.addActionListener(new ActionListener()
		{
			/**
			 * Responds to pressing the enter key in the textfield by sending the contents of the text field to the server. Then clear the text area in preparation for the next message.
			 */
			@Override
			public void actionPerformed(ActionEvent e)
			{
				// TODO: EXIT?
				out.println(textField.getText());
				textField.setText("");
			}
		});
	}
	
	/**
	 * Prompt for and return the address of the server.
	 * @return
	 */
	private String getServerAddress()
	{
		return JOptionPane.showInputDialog(frame, "Enter IP Address of the Server:", "Welcome to the Chatter", JOptionPane.QUESTION_MESSAGE);
	}
	
	/**
	 * Prompt for and return the desired screen name.
	 * @return
	 */
	private String getName()
	{
		return JOptionPane.showInputDialog(frame, "Choose a screen name:", "Screen name selection", JOptionPane.PLAIN_MESSAGE);
	}
	
	/**
	 * Connects to the server then enters the processing loop.
	 * @throws IOException
	 */
	private void run() throws IOException
	{
		
		// Make connection and initialize streams
		String serverAddress = getServerAddress();
		Socket socket = new Socket(serverAddress, 9001);
		in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
		out = new PrintWriter(socket.getOutputStream(), true);
		
		// Process all messages from server, according to the protocol.
		while (true)
		{
			String line = in.readLine();
			if (line.startsWith("SUBMITNAME"))
			{
				out.println(getName());
			}
			else if (line.startsWith("NAMEACCEPTED"))
			{
				textField.setEditable(true);
			}
			else if (line.startsWith("MESSAGE"))
			{
				messageArea.append(line.substring(8) + "\n");
			}
		}
	}
	
	/**
	 * Runs the client as an application with a closeable frame.
	 * @param args
	 * @throws Exception
	 */
	public static void main(String[] args) throws Exception
	{
		Client client = new Client();
		client.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		client.frame.setVisible(true);
		client.run();
	}
}